/*
 * S0101604GN.c
 *
 *  Created on: Jan 12, 2021
 *      Author: xiaolixue
 *
 *  Description:
 *      文件系统掉电安全性测试。目标机上电启动，使用继电器控制电源，
 *      使操作系统在正常运行过程中目标机断开电源，模拟异常掉电情况，
 *      重复操作200次；编写测试用例代码，在目标机上创建文件，并进行
 *      读写操作，验证异常掉电后文件系统仍能正常工作.
 *
 *      针对 SylixOS 平台掉电安全文件系统测试程序
 *
 *      使用说明, 该程序需要在 SylixOS 系统启动之后自动启动, 一段时间后(例如: 2分钟)将目标板进行断电,
 *      然后再上电, 如此过程连续操作 200 次或更多, 通常可以通过继电器实现自动 断电和上电 操作.
 *
 *      该程序编译完成功之后, 可以修改 /etc/startup.sh 的内容, 将该程序加入启动脚本
 */
// #define __USE_GNU       /* 这句要放#include <sched.h>前面 */
#define _GNU_SOURCE
#include <sched.h>


#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sched.h>





#define FILESIZE             (500 * 1024 * 1024)
#define FILEA                "/apps/testsuite_ml/result.log"
#define FILEB                "/apps/testsuite_ml/abc12.txt"
#define FILEC                "/media/sdcard3/c.txt"
#define FILED                "/media/sdcard3/d.txt"
#define FILEE                "/media/hdd0/e.txt"
#define FILEF                "/media/hdd0/f.txt"
#define ERROR_NONE 0


typedef void *PVOID;
/*******************************************************************************************************
** 函数名称: tTest1
** 功能描述: eMMC测试
** 输　入  :
** 输　出  :
*******************************************************************************************************/
PVOID tTest1_fs_611(PVOID pvArg)
{
    int     testfdA;
    int     testfdB;
    int     i      = 1;
    char    buf[5] = { 0 };
    struct  stat stA;
    struct  stat stB;

    sleep(2);

    while (1) {
        if (access(FILEA, F_OK) == 0) {
            stat(FILEA, &stA);

            if (stA.st_size < FILESIZE) {
                testfdA = open(FILEA, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdA < 0) {
                    fprintf(stderr, "open fileA1: files failed.\n");
                    return NULL;
                }

                while (1) {
                    sprintf(buf, "%d ", i);
                    write(testfdA, buf, sizeof(buf));
                    fsync(testfdA);
                    i++;
                    if (i % 1000 == 0) {
                        printf("file %s write.\n", FILEA);
                    }
                }

                close(testfdA);
            } else {

                remove(FILEA);

                printf("file %s operater success.\n", FILEA);

                testfdB = open(FILEB, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdB < 0) {
                    fprintf(stderr, "open fileB1: files failed.\n");
                    return NULL;
                }

                close(testfdB);
                continue;
            }

        } else if (access(FILEB, F_OK) == 0) {
            stat(FILEB, &stB);

            if (stB.st_size < FILESIZE) {

                testfdB = open(FILEB, O_RDWR | O_CREAT | O_APPEND,0666);

                while (1) {
                    sprintf(buf, "%d ", i);

                    if (testfdB < 0) {
                        fprintf(stderr, "open fileB2: files failed.\n");
                        return NULL;
                    }

                    write(testfdB, buf, sizeof(buf));

                    fsync(testfdB);
                    i++;

                    if (i % 1000 == 0) {
                        printf("file %s write.\n", FILEB);
                    }
                }

                close(testfdB);
            } else {
                remove(FILEB);

                printf("file %s operater success.\n", FILEB);
                testfdA = open(FILEA, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdA < 0) {
                    fprintf(stderr, "open fileA2: files failed.\n");
                    return NULL;
                }

                close(testfdA);
                continue;
            }
        } else {
            testfdA = open(FILEA, O_RDWR | O_CREAT | O_APPEND,0666);
            if (testfdA < 0) {
                fprintf(stderr, "open fileA3: files failed.\n");
                return NULL;
            }
            close(testfdA);
        }
    }

    return NULL;
}
/*******************************************************************************************************
** 函数名称: tTest2
** 功能描述: SD-Card 测试
** 输　入  :
** 输　出  :
*******************************************************************************************************/
PVOID tTest2_fs_611(PVOID pvArg)
{
    int     testfdC;
    int     testfdD;
    int     i      = 1;
    char    buf[5] = { 0 };
    struct  stat stC;
    struct  stat stD;

    sleep(2);

    while (1) {
        if (access(FILEC, F_OK) == 0) {
            stat(FILEC, &stC);
            if (stC.st_size < FILESIZE) {
                testfdC = open(FILEC, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdC < 0) {
                    fprintf(stderr, "open fileC1: files failed.\n");
                    return NULL;
                }

                while (1) {
                    sprintf(buf, "%d ", i);
                    write(testfdC, buf, sizeof(buf));

                    fsync(testfdC);
                    i++;
                }
                close(testfdC);

            } else {
                remove(FILEC);
                testfdD = open(FILED, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdD < 0) {
                    fprintf(stderr, "open fileD1: files failed.\n");
                    return NULL;
                }
                close(testfdD);
                continue;
            }

        } else if (access(FILED, F_OK) == 0) {
            stat(FILED, &stD);

            if (stD.st_size < FILESIZE) {

                testfdD = open(FILED, O_RDWR | O_CREAT | O_APPEND,0666);

                while (1) {
                    sprintf(buf, "%d ", i);

                    if (testfdD < 0) {
                        fprintf(stderr, "open fileD2: files failed.\n");
                        return NULL;
                    }

                    write(testfdD, buf, sizeof(buf));

                    fsync(testfdD);
                    i++;
                }

                close(testfdD);
            } else {
                remove(FILED);

                testfdC = open(FILEC, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdC < 0) {
                    fprintf(stderr, "open fileC2: files failed.\n");
                    return NULL;
                }

                close(testfdC);
                continue;
            }
        } else {
            testfdC = open(FILEC, O_RDWR | O_CREAT | O_APPEND,0666);
            if (testfdC < 0) {
                fprintf(stderr, "open fileC3: files failed.\n");
                return NULL;
            }
            close(testfdC);
        }
    }

    return NULL;
}
/*******************************************************************************************************
** 函数名称: tTest3
** 功能描述: SSD 测试
** 输　入  :
** 输　出  :
*******************************************************************************************************/
PVOID tTest3_fs_611(PVOID pvArg)
{
    int     testfdE;
    int     testfdF;
    int     i      = 1;
    char    buf[5] = { 0 };
    struct  stat stE;
    struct  stat stF;

    sleep(2);

    while (1) {
        if (access(FILEE, F_OK) == 0) {
            stat(FILEE, &stE);
            if (stE.st_size < FILESIZE) {
                testfdE = open(FILEE, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdE < 0) {
                    fprintf(stderr, "open fileE1: files failed.\n");
                    return NULL;
                }

                while (1) {
                    sprintf(buf, "%d ", i);
                    write(testfdE, buf, sizeof(buf));

                    fsync(testfdE);
                    i++;

                }
                close(testfdE);

            } else {
                remove(FILEE);

                printf("file %s operater success.\n", FILEE);

                testfdF = open(FILEB, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdF < 0) {
                    fprintf(stderr, "open fileF1: files failed.\n");
                    return NULL;
                }
                close(testfdF);
                continue;
            }

        } else if (access(FILEF, F_OK) == 0) {
            stat(FILEF, &stF);

            if (stF.st_size < FILESIZE) {

                testfdF = open(FILEF, O_RDWR | O_CREAT | O_APPEND,0666);

                while (1) {
                    sprintf(buf, "%d ", i);

                    if (testfdF < 0) {
                        fprintf(stderr, "open fileF2: files failed.\n");
                        return NULL;
                    }

                    write(testfdF, buf, sizeof(buf));

                    fsync(testfdF);
                    i++;
                }
                close(testfdF);

            } else {
                remove(FILEF);

                printf("file %s operater success.\n", FILEF);

                testfdE = open(FILEE, O_RDWR | O_CREAT | O_APPEND,0666);
                if (testfdE < 0) {
                    fprintf(stderr, "open fileE2: files failed.\n");
                    return NULL;
                }
                close(testfdE);
                continue;
            }

        } else {
            testfdE = open(FILEE, O_RDWR | O_CREAT | O_APPEND,0666);
            if (testfdE < 0) {
                fprintf(stderr, "open fileE3: files failed.\n");
                return NULL;
            }
            close(testfdE);
        }
    }

    return NULL;
}
/*******************************************************************************************************
** 函数名称: tTest3
** 功能描述: 测试程序主函数
** 输　入  :
** 输　出  :
*******************************************************************************************************/
int main(int argc, char **argv)
{
    pthread_t           hThreadId1, hThreadId2,hThreadId3;
    pthread_attr_t      threadattr1, threadattr2,threadattr3;
    cpu_set_t           cpuset;

    pthread_attr_init(&threadattr1);
//    pthread_attr_init(&threadattr2);
    //pthread_attr_init(&threadattr3);   // SD卡测试

    pthread_create(&hThreadId1, &threadattr1, tTest1_fs_611, NULL);
//    pthread_create(&hThreadId2, &threadattr2, tTest2_fs_611, NULL);
    //pthread_create(&hThreadId3, &threadattr3, tTest3_fs_611, NULL);  // SD卡测试

    CPU_ZERO(&cpuset);
    CPU_SET(0, &cpuset);
    pthread_setaffinity_np(hThreadId1, sizeof(cpu_set_t), &cpuset);   /*  设置线程hThreadld1在CPU1上运行*/

//    CPU_ZERO(&cpuset);
//    CPU_SET(2, &cpuset);
//    pthread_setaffinity_np(hThreadId2, sizeof(cpu_set_t), &cpuset);   /*  设置线程hThreadld2在CPU2上运行*/

	/*
	 *  SD 卡测试
	 */
    //CPU_ZERO(&cpuset);
    //CPU_SET(3, &cpuset);
    //pthread_setaffinity_np(hThreadId3, sizeof(cpu_set_t), &cpuset);   /*  设置线程hThreadld3在CPU3上运行*/

    return (ERROR_NONE);
}
